#! -*- coding: utf-8 -*-

"""
Baan stpapi wrapper
"""

import sys
#sys.coinit_flags = 0 #pythoncom.COINIT_MULTITHREADED

import pythoncom
import win32com.client
from threading import Lock

BAAN_LOCK = Lock()

class Baan(object):
    def __init__(self,class_string='Baan4.Application',multithread=False):
        if multithread:
            pythoncom.CoInitializeEx(pythoncom.COINIT_MULTITHREADED)
        self.ole = win32com.client.Dispatch(class_string)
        self.ole.Timeout = 300
        self.ole._FlagAsMethod("ParseExecFunction")
        self.ole._FlagAsMethod("Quit")

        self.lock = BAAN_LOCK

    def get_company(self):
        """
        Get the current company name
        """
        self.__ParseExecFunction('ottstp_stddll','get.company()')
        return self.__ReturnValue().strip()

##    def get_compnr(self):
##        """
##        Get the current company number
##        """
##        self.__ParseExecFunction('ottstp_stddll','get.compnr()')
##        return self.__ReturnValue()

    def switch_to_company(self,company_number):
        """
        Switch to another company
        """
        self.__ParseExecFunction('ottstp_stddll','switch.to.company(%s)'%company_number)

    def __ParseExecFunction(self,dll,cmd):
        val = self.ole.ParseExecFunction(dll,cmd)
        if val != 0:
            raise Exception(str(val))
        return val

    def __stpapiParseExecFunction(self,cmd):
        return self.__ParseExecFunction('ottstpapihand',cmd)

    def __FunctionCall(self):
        return self.ole.FunctionCall

    def __parse_result(self,functioncall):
        #print functioncall
        value = functioncall.rsplit(',',1)[1]
        value = value.strip(' \x00)"')
        return value

    def __ReturnValue(self):
        return self.ole.ReturnValue

    def Error(self):
        return self.ole.Error

    def __del__(self):
        """
        Close COM Object on delete
        """
        self.quit()

    def quit(self):
        """
        Close COM Object
        """
        try:
            self.ole.Quit()
        except:
            pass

    def get_field(self,session,field):
        cmd = 'stpapi.get.field ("%(session)s", "%(field)s", "%(value)s")'%{'session':session,
                                                                            'field':field,
                                                                            'value':' '*255}

        self.__stpapiParseExecFunction(cmd)
        value = self.__FunctionCall()
        value = self.__parse_result(value)
        return value

    def put_field(self,session,field,value):
##        if isinstance(value,str):
##            value = '"%s"'%value
##        else:
##            value = str(value)
        cmd = 'stpapi.put.field("%(session)s", "%(field)s", "%(value)s")'%{'session':session,
                                                                            'field':field,
                                                                             'value':value}
        self.__stpapiParseExecFunction(cmd)

    def get_fields(self,session,fields_list):
        result = {}
        for field in fields_list:
            value = self.get_field(session,field)
            result[field] = value
        return result

    def put_fields(self,session,fields_dict):
        for field,value in fields_dict.items():
            self.put_field(session,field,value)

    def set_report(self,session,reportname,device):
        """
        Set session report parameters
        Return error message
        """
        cmd = 'stpapi.set.report("%(session)s","%(reportname)s","%(device)s","%(error)s")'%{'session':session,
                                                                                'reportname':reportname,
                                                                                'device':device,
                                                                                'error':' '*255
                                                                                }
        self.__stpapiParseExecFunction(cmd)
        result = self.__FunctionCall()
        return self.__parse_result(result)

    def continue_process(self,session):
        """
        send start command of the process
        return error message
        """
        cmd = 'stpapi.continue.process("%(session)s","%(error)s")'%{'session':session,'error':' '*255}
        self.__stpapiParseExecFunction(cmd)
        result = self.__FunctionCall()
        return self.__parse_result(result)

    def insert(self,session,do_save=1):
        """This inserts the current record of the specified session into the database. The
        values of the fields in the session must be set before calling this function.
        """
        cmd = 'stpapi.insert("%(session)s",%(do_save)d,"%(error)s")'%{'session':session,'do_save':do_save,'error':' '*255}
        self.__stpapiParseExecFunction(cmd)
        result = self.__FunctionCall()
        return self.__parse_result(result)

    def save(self,session):
        """
        This executes the choice section update.db of the specified session. Note
        that the same effect can be achieved by issuing any of the following
        functions:
         stpapi.insert()
         stpapi.update()
        with the do.save parameter set to 1.
        """
        cmd = 'stpapi.insert("%(session)s","%(error)s")'%{'session':session,'error':' '*255}
        self.__stpapiParseExecFunction(cmd)
        result = self.__FunctionCall()
        return self.__parse_result(result)

    def end_session(self,session):
        cmd = 'stpapi.end.session("%(session)s")'%{'session':session}
        self.__stpapiParseExecFunction(cmd)

    def find(self,session):
        cmd = 'stpapi.find("%(session)s")'%{'session':session}
        self.__stpapiParseExecFunction(cmd)

    def find2(self,session,parameters):
        for key,value in parameters.items():
            self.put_field(session,key,value)
        self.find(session)

    def browse_set(self,session,option):
        cmd = 'stpapi.browse.set( "%(session)s", "%(option)s" )'%{'session':session,'option':option}
        self.__stpapiParseExecFunction(cmd)

    def first_set(self,session):
        self.browse_set(session,'first.set')

    def last_set(self,session):
        self.browse_set(session,'last.set')

    def next_set(self,session):
        self.browse_set(session,'next.set')

    def prev_set(self,session):
        self.browse_set(session,'prev.set')


def test():    #test
    import threading
    import time

    d = Baan(multithread=True)
    d.first_set('tiitm0101m000')
    print d.get_company(),d.get_field('tiitm0101m000','tiitm001.item')
    d.end_session('tiitm0101m000')

    def thread_test(company,sleep=1):
        b = Baan(multithread=True)
        b.switch_to_company(company)
        for i in range(10):
            b.first_set('tiitm0101m000')
            print i,company,
            print b.get_field('tiitm0101m000','tiitm001.item'),
            b.end_session('tiitm0101m000')
            print b.get_company()
            time.sleep(sleep)
        b.quit()

    t_a = threading.Thread(target=thread_test,kwargs={'company':300,'sleep':1.2})
    t_b = threading.Thread(target=thread_test,kwargs={'company':400,'sleep':1})
    t_c = threading.Thread(target=thread_test,kwargs={'company':500,'sleep':1.1})

    t_a.start()
    time.sleep(0.5)
    t_b.start()
    time.sleep(0.5)
    t_c.start()

    while threading.active_count() > 1:
        time.sleep(0.2)

    d.quit()

if __name__ == '__main__':
    test()
    raw_input('')
##    b = Baan()

